#if !defined(_SNG_LOG__INCLUDED_)
#define _SNG_LOG__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////
// SNGLOG

#include <io.h>
#include <stdio.h>
//#include <iostream>

class SNGLOG
{
private:
	CRITICAL_SECTION m_cs;
	FILE* m_file;
	char filename[MAX_PATH];
	char stime[32];
	char str[260];
	char str1[260];

	void putMessage(LPCSTR s, BOOL bClose)
	{
//		cout << s;
		if(m_file != NULL)
		{
			if(s != NULL) fprintf(m_file, "%s", s);
			if(bClose) { fclose(m_file); m_file = NULL; }
			else { fflush(m_file); }
		}
	};

	char* getSysTime()
	{
		SYSTEMTIME st;
		GetLocalTime(&st);
		sprintf(stime, "%.2i/%.2i %.2i:%.2i:%.2i.%.3i", st.wMonth, st.wDay,
				st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
		return stime;
	}

public:
	SNGLOG()
	{
		InitializeCriticalSection(&m_cs);
		EnterCriticalSection(&m_cs);
		m_file = NULL;
		LeaveCriticalSection(&m_cs);
	};

	~SNGLOG()
	{
		stopLogging();
		DeleteCriticalSection(&m_cs);
	};
/*
	void startLogging(LPCSTR fname)
	{
		stopLogging();

		strncpy(filename, fname, sizeof(filename)-2);
		m_file = fopen(filename, "a+t");
		if(m_file != NULL)
		{
			m_written = _filelengthi64(fileno(m_file));
		}
		if(m_file != NULL)
		{
			EnterCriticalSection(&m_cs);
			sprintf(str, "--------------- Logging started at %s ---------------\n", getSysTime());
			putMessage(str, FALSE);
			LeaveCriticalSection(&m_cs);
		}
	};
*/
	void startLogging(ULONG ip)
	{
		SYSTEMTIME st;

		stopLogging();

		sprintf(str, "%.3i%.3i%.3i%.3i",
				(int)ip&0xFF, (int)((ip>>8)&0xFF), (int)((ip>>16)&0xFF), (int)((ip>>24)&0xFF));
		GetLocalTime(&st);
		switch(st.wMonth)
		{
			case  1: strcat(str, "Jan"); break;
			case  2: strcat(str, "Feb"); break;
			case  3: strcat(str, "Mar"); break;
			case  4: strcat(str, "Apr"); break;
			case  5: strcat(str, "May"); break;
			case  6: strcat(str, "Jun"); break;
			case  7: strcat(str, "Jul"); break;
			case  8: strcat(str, "Aug"); break;
			case  9: strcat(str, "Sep"); break;
			case 10: strcat(str, "Oct"); break;
			case 11: strcat(str, "Nov"); break;
			case 12: strcat(str, "Dec"); break;
			default: strcat(str, "---"); break;
		}
		sprintf(filename, "%s%.2i%.4i%.2i%.2i%.2i.log", str,
				(int)st.wDay, (int)st.wYear, (int)st.wHour, (int)st.wMinute, (int)st.wSecond);

		m_file = fopen(filename, "a+t");
/*
		if(m_file != NULL)
		{
			EnterCriticalSection(&m_cs);
			sprintf(str, "--------------- Logging started at %s ---------------\n", getSysTime());
			putMessage(str, FALSE);
			LeaveCriticalSection(&m_cs);
		}
*/
	};

	void startLogging(const char* name)
	{
		strncpy(filename, name, sizeof(filename)-2);
		m_file = fopen(filename, "a+t");
	};

	void stopLogging(BOOL bDelete = FALSE)
	{
		if(m_file != NULL)
		{
			EnterCriticalSection(&m_cs);
/*
			sprintf(str, "--------------- Logging stopped at %s ---------------\n", getSysTime());
			putMessage(str, TRUE);
*/
			putMessage(NULL, TRUE);

			if(bDelete && filename[0])
			{
				remove(filename);
				filename[0] = '\0';
			}

			LeaveCriticalSection(&m_cs);
		}
	};

	void error(LPCSTR pFStr, va_list aList)
	{
		output(" ** error ", NULL, 0, pFStr, aList);
	};

	void error(LPCSTR sFile, int sLine, LPCSTR pFStr, va_list aList)
	{
		output(" ** error ", sFile, sLine, pFStr, aList);
	};

	void error(LPCTSTR pFStr, ...)
	{
		va_list aList;
		va_start(aList, pFStr);
		error(pFStr, aList);
		va_end(aList);
	};

	void error(LPCSTR sFile, int sLine, LPCTSTR pFStr, ...)
	{
		va_list aList;
		va_start(aList, pFStr);
		error(sFile, sLine, pFStr, aList);
		va_end(aList);
	};

	void message(LPCSTR pFStr, va_list aList)
	{
		output("", NULL, 0, pFStr, aList);
	};

	void message(LPCSTR sFile, int sLine, LPCSTR pFStr, va_list aList)
	{
		output("", sFile, sLine, pFStr, aList);
	};

	void message(LPCTSTR pFStr, ...)
	{
		va_list aList;
		va_start(aList, pFStr);
		message(pFStr, aList);
		va_end(aList);
	};

	void message(LPCSTR sFile, int sLine, LPCTSTR pFStr, ...)
	{
		va_list aList;
		va_start(aList, pFStr);
		message(sFile, sLine, pFStr, aList);
		va_end(aList);
	};

	void warning(LPCSTR pFStr, va_list aList)
	{
		output(" ** warning ", NULL, 0, pFStr, aList);
	};

	void warning(LPCSTR sFile, int sLine, LPCSTR pFStr, va_list aList)
	{
		output(" ** warning ", sFile, sLine, pFStr, aList);
	};

	void warning(LPCTSTR pFStr, ...)
	{
		va_list aList;
		va_start(aList, pFStr);
		warning(pFStr, aList);
		va_end(aList);
	};

	void warning(LPCSTR sFile, int sLine, LPCTSTR pFStr, ...)
	{
		va_list aList;
		va_start(aList, pFStr);
		warning(sFile, sLine, pFStr, aList);
		va_end(aList);
	};

	void output(LPCSTR type, LPCSTR sFile, int sLine, LPCSTR pFStr, va_list aList)
	{
		EnterCriticalSection(&m_cs);
		vsprintf(str1, pFStr, aList);
		if((sFile != NULL) && (sLine != 0))
		{
			LPSTR fn = strrchr(sFile, (int)('\\'));
			fn = (fn != NULL) ? fn + 1 : (LPSTR)sFile;
//			sprintf(str, "%s - %s...%s(%i)... %s\n", getSysTime(), type, fn, sLine, str1);
			sprintf(str, "%s\n", str1);
		}
		else
		{
//			sprintf(str, "%s -%s- %s\n", getSysTime(), type, str1);
			sprintf(str, "%s\n", str1);
		}
		putMessage(str, FALSE);
		LeaveCriticalSection(&m_cs);
	};
};

#endif // !defined(_SNG_LOG__INCLUDED_)
